/*
 * Copyright (C) 2009 2DAI
 *
 * Este programa es Software Libre; usted puede redistribuirlo
 * y/o modificarlo bajo los términos de la "GNU General Public
 * License" como lo publica la "FSF Free Software Foundation",
 * o (a su elección) de cualquier versión posterior.
 *
 * Este programa es distribuido con la esperanza de que le será
 * útil, pero SIN NINGUNA GARANTIA; incluso sin la garantía
 * implícita por el MERCADEO o EJERCICIO DE ALGUN PROPOSITO en
 * particular. Vea la "GNU General Public License" para más
 * detalles.
 *
 * Usted debe haber recibido una copia de la "GNU General Public
 * License" junto con este programa, si no, escriba a la "FSF
 * Free Software Foundation, Inc.", 59 Temple Place - Suite 330,
 * Boston, MA  02111-1307, USA.
 */
package logic;

import data.DataManager;
import gui.TableiFrame;
import gui.MainWindow;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import javax.swing.JTable;
import javax.swing.SwingWorker;
import util.AudioPlayer;
import util.Errors;
import on.EventsCalendar;
import util.Sql;

/**
 *
 * Author: Jorge Garrido Oval
 * Colaborated: José Iván Palmer García
 * Logica que maneja los datos de las tablas.
 */
public class TableLogic extends SwingWorker<Void, Void> implements MouseListener {

    private DataManager dm;
    private MainWindow mw;
    private TableiFrame tf;
    private TableContent tc;
    private int opcion = 100;
    private String titulo;
    //En este array se pondran todas las clases derivadas de DataManager que
    //deban usar esta logica, con el mismo orden que se numeran en la ventana principal
    private String[] dml = {"DataStandingsTeam", "DataCalendary", "DataRanking"};
    private String[][] col = {{"Equipo", "E.Jugados", "E.Ganados", "E.Perdidos", "P.a Favor", "P.en Contra", "Puntos"},
        {"Local", "Visitante", "Categoria", "Dia", "Arbitro"},
        {"Jugador", "Posición", "PosicionAnterior", "PuntosInicioMes",
            "PuntosJornada", "PuntosFinalMes", "PartidosJugadosMes",
            "PartidosGanadosMes", "PartidosPerdidosMes"}};

    //Constructores
    public TableLogic() {
        dm = null;
    }

    public TableLogic(MainWindow mw) {
        this();
        tf = new TableiFrame(this);
        this.mw = mw;
        this.mw.getJDPescritorio().add(tf);
        this.mw.repaint();
    }

    public TableLogic(MainWindow mw, String titulo) {
        this(mw);
        this.titulo = titulo;
        tf.setTitle(titulo);
    }

    public TableLogic(MainWindow mw, String titulo, int opcion) {
        this(mw, titulo);
        this.opcion = opcion;
    }

    //Métodos
    /**
     * Uso de la característica de reflexión de Java.
     * Se llaman a las clases para instanciarlas de forma dinámica llamandolas
     * por su nombre, esta funcion se realiza una cuando las clases ya estan
     * compiladas, en tiempo de ejecucion. Con esto evitamos un switch o una
     * batería de If's que ralentizarian el programa.
     * Tened en cuenta que newInstance() siempre llama al constructor vacio.
     * @param opcion
     */
    private void seleccionaFuente(int opcion) {
        try {
            dm = (DataManager) Class.forName("data." + dml[opcion]).newInstance();
        } catch (InstantiationException ex) {
            Errors.creaError("ERROR: No se ha podido instanciar clase derivada " +
                    "de DataManager/JPanel\n" + ex.getMessage(), ex.getStackTrace());
        } catch (IllegalAccessException ex) {
            Errors.creaError("ERROR: No se ha podido acceder a la clase derivada " +
                    "de DataManager/JPanel\n" + ex.getMessage(), ex.getStackTrace());
        } catch (ClassNotFoundException ex) {
            Errors.creaError("ERROR: No existe se encuentra la clase derivada " +
                    "de DataManager/JPanel\n" + ex.getMessage(), ex.getStackTrace());
        }
    }

    /**
     * Este método hace que las ventanas vibren
     */
    private void vibrar() {
        final int originalX = tf.getX();
        final int originalY = tf.getY();
        try {
            for (int i = 0; i < 5; i++) {
                Thread.sleep(10);
                tf.setLocation(tf.getX(), tf.getY() + 5);
                Thread.sleep(10);
                tf.setLocation(tf.getX(), tf.getY() - 5);
                Thread.sleep(10);
                tf.setLocation(tf.getX() - 5, tf.getY());
                Thread.sleep(10);
                tf.setLocation(originalX, originalY);
            }
        } catch (Exception ex) {
            Errors.creaAdvertencia("La posisción no es correcta, la ventana no vibrará.", ex.getStackTrace());
        }
    }

    /**
     * Método heredado de SwingWorker para cambar la la barrada de progreso
     * @return no retorna nada
     * @throws java.lang.Exception
     */
    @Override
    protected Void doInBackground() throws Exception {
        //Initialize progress property.
        setProgress(50);
        this.seleccionaFuente(getOpcion());
        tc = new TableContent(dm, col[getOpcion()].length, getOpcion());
        tf.ponerDatos(tc.getDatos(), col[getOpcion()]);
        setProgress(100);
        new AudioPlayer(System.getProperty("user.dir") + "/src/audio/zumbido.wav").start();
        vibrar();
        return null;
    }

    /**
     * Retorna la opcion para diferenciar las clases
     * @return the opcion
     */
    public int getOpcion() {
        return opcion;
    }

    /**
     * Hace visible el panel de tabla actual
     */
    public void setVisible() {
        tf.setVisible(true);
    }

    public void mouseClicked(MouseEvent e) {
        if (this.titulo.compareTo("Calendario de eventos") == 0 && e.getClickCount() == 2) {
            Sql sql = new Sql();
            sql.conectar();
            JTable t = (JTable) e.getSource();
            int fila = t.rowAtPoint(e.getPoint());
            int columna = t.columnAtPoint(e.getPoint());
            if ((fila > -1) && (columna > -1)) {
                try {
                    EventsCalendar calendario = new EventsCalendar();
                    calendario.setEquipoLocal((String) tc.getDatos()[fila][0]);
                    calendario.setEquipoVisitante((String) tc.getDatos()[fila][1]);
                    calendario.setCategoria((String) tc.getDatos()[fila][2]);
                    calendario.setDiaHora((Date) tc.getDatos()[fila][3]);
                    calendario.setArbitro((String) tc.getDatos()[fila][4]);
                    ResultSet rs = sql.ejecutarSelect("SELECT DISTINCT id_record FROM record r " +
                            "JOIN calendarymeeting c ON (r.local_team = " +
                            calendario.getEquipoLocal() + " AND r.visiting_team = " +
                            calendario.getEquipoVisitante() + " AND r.fecha = '" +
                            calendario.getDiaHora().toString() + "') JOIN referee ref ON (ref.last_name LIKE '" +
                            calendario.getArbitro() + "');");
                    while (rs.next()) {
                        new RecordLogic(mw, rs.getInt(1)).execute();
                    }
                } catch (SQLException ex) {
                    Errors.creaError("No se puede seleccionar el acta.", ex.getStackTrace());
                }
            }
        }
    }

    public void mousePressed(MouseEvent e) {
    }

    public void mouseReleased(MouseEvent e) {
    }

    public void mouseEntered(MouseEvent e) {
    }

    public void mouseExited(MouseEvent e) {
    }
}
